(in-package #:experiment)

(defclass event ()
  ()
  (:documentation "An event."))

(defclass click-event (event)
  ((source :initarg :source :accessor click-event-source)
   (x :initform nil :initarg :x :accessor click-event-x)
   (y :initform nil :initarg :y :accessor click-event-y)))

(defmethod print-object ((obj click-event) stream)
  (print-unreadable-object (obj stream :type t :identity t)
    (with-slots (source) obj
        (format stream "~s" source))))

(defclass key-press-event (event)
  ((key :initarg :key :accessor key-press-event-key)))

(defmethod print-object ((obj key-press-event) stream)
  (print-unreadable-object (obj stream :type t :identity t)
    (with-slots (key) obj
        (format stream "~s" key))))

(defclass timer-event (event)
  ((tag :initform nil :initarg :tag :accessor timer-event-tag)))

(defmethod print-object ((obj timer-event) stream)
  (print-unreadable-object (obj stream :type t :identity t)
    (with-slots (tag) obj
        (format stream "~s" tag))))

(define-event-match timeout (state (event timer-event) tag)
  (if tag-supplied
      (eq (timer-event-tag event) tag)
      (or (timer-event-tag event) t)))

(define-event-match click (state (event click-event) source)
  (if source-supplied
      (eq (click-event-source event) source)
      (or (click-event-source event) t)))

(define-event-match click-inside (state (event click-event) x y width height)
  (or (not x-supplied)
      (not y-supplied)
      (not width-supplied)
      (not height-supplied)
      (and (>= (click-event-x event) x)
           (>= (click-event-y event) y)
           (< (click-event-x event) (+ x width))
           (< (click-event-y event) (+ y height)))))

(define-event-match keypress (state (event key-press-event) sym char)
  (and (or (not sym-supplied)
           (eq (gwee:key-sym (key-press-event-key event)) sym))
       (or (not char-supplied)
           (let ((ch (gwee:key-to-character (key-press-event-key event))))
             (and (characterp ch)
                  (char= char ch))))))
